package top.zlhy7.lock;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

/**
 * @author renyong
 * @date 2022/8/13 13:55
 * @description juc辅助类练习
 */
@Slf4j
public class CountDownLatchDemo {
    public static void main(String[] args) {
        CountDownLatchDemo countDownLatchDemo = new CountDownLatchDemo();
        countDownLatchDemo.test3();
    }
    /**
     * 减少计数 CountDownLatch
     * 比如：当6个同学离开教室后才关门
     * @throws Exception
     */
    @Test
    public void 不加CountDownLatch() throws Exception{
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                log.info("第{}位同学离开教室",Thread.currentThread().getName());
            },String.valueOf(i+1)).start();
        }
        /*
        this is our friend Li Ming .Li Ming lives in China./
         */
    }
    /**
     * 减少计数 CountDownLatch
     * 比如：当6个同学离开教室后才关门
     * @throws Exception
     */
    @Test
    public void test1() throws Exception{
        //创建计数器，赋初始值6
        CountDownLatch countDownLatch = new CountDownLatch(6);
        for (int i = 0; i < 6; i++) {
            new Thread(()->{
                log.info("第{}位同学离开教室",Thread.currentThread().getName());

                countDownLatch.countDown();
            },String.valueOf(i+1)).start();
        }
        //等待
        countDownLatch.await();
        log.info("完成了");
    }

    /**
     * CyclicBarrier 循环栅栏练习
     * 例子：收集7颗龙珠，当7颗龙珠收集到之后才能召唤神龙
     */
    @Test
    public void test2() throws Exception{
        log.info("循环栅栏练习");
        // 构造方法(固定值，达到条件后要做什么事情)
        CyclicBarrier cyclicBarrier = new CyclicBarrier(7,()-> System.out.println("集齐7颗龙珠召唤神龙"));
        for (int i = 1; i <= 7; i++) {
            new Thread(()->{
                System.out.println(Thread.currentThread().getName()+"星龙珠被收集到了");
                try {
                    cyclicBarrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    throw new RuntimeException(e);
                }
            },String.valueOf(i)).start();
        }
    }

    /**
     * Semaphore 信号灯
     * 示例：6辆汽车，3个停车位，模拟该过程
     */
    @Test
    public void test3(){
        Semaphore semaphore = new Semaphore(3);
        for (int i = 1; i <= 6; i++) {
            new Thread(()->{
                try {
                    //抢占车位
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName()+"抢占车位");
                    //设置随机停车时间
                    TimeUnit.SECONDS.sleep((int)(Math.random()*5));
                    System.out.println(Thread.currentThread().getName()+"------离开了车位");
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }finally {
                    semaphore.release();
                }
            },String.valueOf(i)).start();
        }
    }
}
